package com.hatchsolution.ftp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.NoSuchElementException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;

import com.hatchsolution.ftp.exception.FTPClientException;
import com.hatchsolution.ftp.pool.impl.FTPPool;

/*
 * FTPUtils 
 * @author gary-pc
 *
 */
public class FTPUtils {
	
	
	private static Logger logger = Logger.getLogger(FTPUtils.class) ;
	
	
	private FTPPool pools ;
	/**
	 * 
	 * @param fileName
	 * @param in
	 * @return
	 * @throws NoSuchElementException
	 * @throws IllegalStateException
	 * @throws Exception
	 */
	public Boolean appendFile(String fileName,InputStream in) throws NoSuchElementException, IllegalStateException, Exception{
		Boolean flag = false ;
		
		if(StringExtend.isNullOrEmpty(fileName)) {
			 throw new RuntimeException("upload fileName must be required !");  
		}
		FTPClient ftpClient = pools.borrowObject() ;
		try {
			flag = ftpClient.appendFile(new String(fileName.getBytes("UTF-8"),"iso-8859-1"), in) ;
		} catch (Exception e) {
			throw e ;
		}finally {
			pools.returnObject(ftpClient);
		}
		return flag ;
	}
	
	
	public Boolean isFTPFileExist(String ftpName){
		
		Boolean flag = false ;
		if(!StringExtend.isNullOrEmpty(ftpName)){
			FTPClient ftpClient = null ;
			try {
				String dir = PathExtend.getDirectory(ftpName) ;
				ftpClient = pools.borrowObject() ;
				ftpClient.changeWorkingDirectory(dir) ;
				String ftpFileName = PathExtend.getFileName(ftpName) ;
				InputStream inputStream = ftpClient.retrieveFileStream(ftpFileName);
				int returnCode = ftpClient.getReplyCode();
				if (inputStream == null || returnCode == 550) {
				    flag = false;
				}else{
					flag = true;
				}
				
				if(inputStream != null){
					inputStream.close();
		            ftpClient.completePendingCommand();
		        }
			} catch (Exception e) {
				 flag = false;
			}finally {
				if(ftpClient != null){
					pools.returnObject(ftpClient);
				}
			}
			
		}
		return flag ;
		
	}
	
	
	
	/**
	 * 
	 * @param path
	 * @param fileName
	 * @param in
	 * @return
	 * @throws NoSuchElementException
	 * @throws IllegalStateException
	 * @throws Exception
	 */
	public Boolean appendFile(String path,String fileName,InputStream in) throws NoSuchElementException, IllegalStateException, Exception {
		FTPClient ftpClient = pools.borrowObject() ;
		Boolean flag = false ;
		
		
		if(StringExtend.isNullOrEmpty(fileName)) {
			 throw new RuntimeException("upload fileName must be required !");  
		}
		
		try {
			if(!createDir(ftpClient,path)){
				throw new FTPClientException("cd dir error"+path) ;
			}
			flag = ftpClient.appendFile(new String(fileName.getBytes("UTF-8"),"iso-8859-1"), in) ;
		} catch (Exception e) {
			throw e ;
		}finally {
			pools.returnObject(ftpClient);
		}
		return flag ;
	}
	/**
	 * 
	 * @param ftpClient
	 * @param dir  eg /ftp or /ftp/
	 * @return
	 * @throws IOException 
	 * @throws FTPClientException 
	 */
	public Boolean createDir(FTPClient ftpClient,String dir) throws IOException, FTPClientException{
		String d;
		if (ftpClient != null && dir != null && dir.length() > 0) {
			d = new String(dir.toString().getBytes("UTF-8"), "iso-8859-1");
			if (ftpClient.changeWorkingDirectory(dir)) {
				return true;
			}
			dir = StringExtend.trimStart(dir, "/");
			dir = StringExtend.trimEnd(dir, "/");
			String[] arr = dir.split("/");
			StringBuffer sbfDir = new StringBuffer();
			for (String s : arr) {
				sbfDir.append("/");
				sbfDir.append(s);
				d = new String(sbfDir.toString().getBytes("UTF-8"), "iso-8859-1");
				if (ftpClient.changeWorkingDirectory(d)) {
					continue;
				}

				if (!ftpClient.makeDirectory(d)) {
					throw new FTPClientException("[create dir error]：" + sbfDir.toString()) ;
				}
			}

		}
		return ftpClient.changeWorkingDirectory(dir);
		
	}
	/**
	 * 
	 * @param path /sample/ or null
	 * @param fileName
	 * @return
	 * @throws NoSuchElementException
	 * @throws IllegalStateException
	 * @throws Exception
	 */
	public Boolean deleteFile(String path,String fileName ) throws NoSuchElementException, IllegalStateException, Exception{
		FTPClient ftpClient = pools.borrowObject() ;
		Boolean flag = false ;
		String dir ="" ;
		if(!StringExtend.isNullOrEmpty(path)){
			dir = StringExtend.trimEnd(path, "/") ;
			dir = StringExtend.trimStart(path,"/") ;
			dir = dir+File.separator ;
		}
		try {
			flag = ftpClient.deleteFile(dir+fileName) ;
		} catch (Exception e) {
			throw e ;
		}finally {
			pools.returnObject(ftpClient);
		}
		return flag ;
	}
	
	/**
	 * 
	 * @param remoteFile /sample/aa.png
	 * @return
	 * @throws NoSuchElementException
	 * @throws IllegalStateException
	 * @throws Exception
	 */
	public InputStream getInputStream(String remoteFile) throws NoSuchElementException, IllegalStateException, Exception{
		InputStream in = null ;
		FTPClient ftpClient = pools.borrowObject() ;
		try {
			if(StringExtend.isNullOrEmpty(remoteFile) && ftpClient.remoteRetrieve(remoteFile)){
				in = ftpClient.retrieveFileStream(remoteFile) ;
			}
		} catch (Exception e) {
			throw e ;
		}finally {
			pools.returnObject(ftpClient);
		}
		return in ;
	}
	
	/**
	 * borrow ftpClient
	 * @return
	 * @throws Exception
	 */
	public FTPClient borrowFTPClient() throws Exception {
		return pools.borrowObject() ;
	}
	
	/**
	 * 
	 * @param ftpClient
	 */
	public void returnFTPClient(FTPClient ftpClient) {
		pools.returnObject(ftpClient);
	}
	
	/**
	 * 
	 * @param remoteFile /sample/aa.png
	 * @param out
	 * @throws NoSuchElementException
	 * @throws IllegalStateException
	 * @throws Exception
	 */
	public void retrieveFile(String remoteFile,OutputStream out) throws NoSuchElementException, IllegalStateException, Exception{
		FTPClient ftpClient = pools.borrowObject() ;
		try {
			if(!StringExtend.isNullOrEmpty(remoteFile) && out != null){
				ftpClient.retrieveFile(remoteFile, out) ;
			}
		} catch (Exception e) {
			throw e ;
		}finally {
			pools.returnObject(ftpClient);
		}
	}
	public FTPPool getPools() {
		return pools;
	}
	public void setPools(FTPPool pools) {
		this.pools = pools;
	}
	
	
	
	
	
 }
